﻿using Microsoft.AspNetCore.Http;
using Microsoft.Net.Http.Headers;

namespace 日志的使用
{
    /// <summary>
    /// 自定义中间件 -根据约定
    /// 1.至少有一个包含 RequestDelegate类型参数的构造函数
    /// 2.定义一个名称为 Invoke或 InvokeAsync的方法，并且该方法至少接收一个HttpContext类型的参数，返回值为Task类型
    /// 3.将该定义的中间件类添加 program文件的 Map中 app.UseMiddleware<SelfMiddleware>();
    /// 4.中间件之间会共享 Httpcontext.Items["Key"] 中的内容
    /// </summary>
    public class SelfMiddleware
    {
        private readonly RequestDelegate next;
        private readonly string webRootPath;
        public SelfMiddleware(RequestDelegate next, string webRootPath)
        {
            this.next = next;
            this.webRootPath = webRootPath;

        }

        /// <summary>
        /// 在本网站内部访问时，Http请求中会包含一个referer参数，里面存放的是网站的根路径
        /// 防盗链的基本使用
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task InvokeAsync(HttpContext context)
        {
            if ((context.Request.Path.Value.Contains("jpg")) || context.Request.QueryString.Value.Contains("jpg"))
            {
                var appUrl = $"{context.Request.Scheme}://{context.Request.Host.Value}";
                var headerDic = context.Request.Headers;
                var urlReferer = headerDic[HeaderNames.Referer].ToString();
                if (string.IsNullOrEmpty(urlReferer) || !urlReferer.StartsWith(appUrl))
                {
                    //返回一个禁止访问的图片
                    string unImageUrl = $"{Directory.GetCurrentDirectory()}\\{webRootPath}\\NoImage.jpg";
                    context.Request.EnableBuffering();
                    context.Request.Body.Position = 0;
                    var responseStream = context.Response.Body;
                    using (FileStream stream = new FileStream(unImageUrl, FileMode.Open))
                    {
                        context.Response.Body = stream;
                        stream.Position = 0;
                        var responseReader = new StreamReader(stream);
                        string? responseContent = await responseReader.ReadToEndAsync();
                        stream.Position = 0;
                        await stream.CopyToAsync(responseStream);
                        context.Response.Body = responseStream;
                        return;
                    }
                }
            }
            await next(context);
        }
    }
}
